using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace Acms.AcmsControls
{
    [ToolboxData("<{0}:UserLogonControl runat=server></{0}:UserLogonControl>")]
    public class UserLogonControl : CompositeControl
    {
        public enum Mode
        {
            Login,
            ForgottenPassword
        }

        protected override void OnLoad(EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                returnUrl = Page.Request.QueryString["ReturnUrl"];
            }
            base.OnLoad(e);
        }

        string returnUrl;

        protected override HtmlTextWriterTag TagKey
        {
            get
            {
                return HtmlTextWriterTag.Div;
            }
        }

        private string errorMessageClass = "errorMessage";
        public string ErrorMessageClass
        {
            get { return errorMessageClass; }
            set { errorMessageClass = value; }
        }

        private string messageClass = "message";
        public string MessageClass
        {
            get { return messageClass; }
            set { messageClass = value; }
        }

        private string invalidUserNameOrPasswordMessage = "Invalid username and/or password. Please try again or use forgotten password.";
        public string InvalidUserNameOrPasswordMessage
        {
            get { return invalidUserNameOrPasswordMessage; }
            set { invalidUserNameOrPasswordMessage = value; }
        }

        private string emailNotFoundMessage = "Could not find this email address in our database.";
        public string EmailNotFoundMessage
        {
            get { return emailNotFoundMessage; }
            set { emailNotFoundMessage = value; }
        }


        private string sentForgottenPasswordMessage = "Sent forgotten password email. Please check your inbox.";
        public string SentForgottenPasswordMessage
        {
            get { return sentForgottenPasswordMessage; }
            set { sentForgottenPasswordMessage = value; }
        }


        private string forgottenPasswordInstructions = "Please enter your email address to reset your password.";

        public string ForgottenPasswordInstructions
        {
            get { return forgottenPasswordInstructions; }
            set { forgottenPasswordInstructions = value; }
        }
	
	

        private Mode currentMode = Mode.Login;

        public Mode CurrentMode
        {
            get { return currentMode; }
            set { currentMode = value; }
        }
	

        protected override object SaveViewState()
        {
            ViewState["ReturnUrl"] = returnUrl;
            ViewState["CurrentMode"] = currentMode;
            return base.SaveViewState();
        }

        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);
            returnUrl = ViewState["ReturnUrl"] as string;
            if(ViewState["CurrentMode"] is Mode)
                currentMode = (Mode)ViewState["CurrentMode"];
        }

        TextBox username;
        TextBox password;
        RequiredFieldValidator valUsernameReq;
        RequiredFieldValidator valPasswordReq;
        Button btnLogon;
        Button btnForgottenPassword;
        CheckBox cbRemember;
        bool invalidPassword;
        bool invalidUsername;
        bool invalidEmail;
        bool sentEmail;

        TextBox txtEmail;
        RequiredFieldValidator valEmailReq;
        Button btnSendForgottenPassword;
        Button btnCancelForgottenPassword;


        protected override void CreateChildControls()
        {
            this.Controls.Clear();

            username = InitTextBox("username");

            valUsernameReq = new RequiredFieldValidator();
            InitControl(valUsernameReq, "valUsernameReq");
            valUsernameReq.ErrorMessage = "!Required";
            valUsernameReq.ControlToValidate = username.ID;
            valUsernameReq.ValidationGroup = string.Concat(this.ClientID, "_Login");

            password = InitTextBox("password");
            password.TextMode = TextBoxMode.Password;

            valPasswordReq = new RequiredFieldValidator();
            InitControl(valPasswordReq, "valPasswordReq");
            valPasswordReq.ErrorMessage = "!Required";
            valPasswordReq.ControlToValidate = password.ID;
            valPasswordReq.ValidationGroup = string.Concat(this.ClientID, "_Login");

            cbRemember = new CheckBox();
            InitControl(cbRemember, "cbRemember");

            btnLogon = new Button();
            InitControl(btnLogon, "btnLogon");
            btnLogon.Text = "Logon";
            btnLogon.Click += new EventHandler(btnLogon_Click);
            btnLogon.ValidationGroup = string.Concat(this.ClientID, "_Login");

            btnForgottenPassword = new Button();
            InitControl(btnForgottenPassword, "btnForgotten");
            btnForgottenPassword.CausesValidation = false;
            btnForgottenPassword.Text = "Forgotten Password";
            btnForgottenPassword.Click += new EventHandler(btnForgottenPassword_Click);

            txtEmail = InitTextBox("txtEmail");

            valEmailReq = new RequiredFieldValidator();
            InitControl(valEmailReq, "valEmailReq");
            valEmailReq.ErrorMessage = "!Required";
            valEmailReq.ControlToValidate = txtEmail.ID;
            valEmailReq.ValidationGroup = string.Concat(this.ClientID, "_Forgotten");

            btnSendForgottenPassword = new Button();
            InitControl(btnSendForgottenPassword, "btnSendForgottenPassword");
            btnSendForgottenPassword.CausesValidation = true;
            btnSendForgottenPassword.Text = "Send";
            btnSendForgottenPassword.ValidationGroup = string.Concat(this.ClientID, "_Forgotten");
            btnSendForgottenPassword.Click += new EventHandler(btnSendForgottenPassword_Click);

            btnCancelForgottenPassword = new Button();
            InitControl(btnCancelForgottenPassword, "btnCancelForgottenPassword");
            btnCancelForgottenPassword.Text = "Cancel";
            btnCancelForgottenPassword.CausesValidation = false;
            btnCancelForgottenPassword.Click += new EventHandler(btnCancelForgottenPassword_Click);

            base.CreateChildControls();
        }

        void btnCancelForgottenPassword_Click(object sender, EventArgs e)
        {
            CurrentMode = Mode.Login;
        }

        void btnSendForgottenPassword_Click(object sender, EventArgs e)
        {
            if (Page.IsValid)
            {
                //get user send password
                Acms.Bll.UserSecurity user = Acms.Bll.UserSecurity.GetByEmailAddress(txtEmail.Text, SiteId);
                if (user != null)
                {
                    user.SendForgottenEmail();
                    sentEmail = true;
                }
                else
                {
                    invalidEmail = true;
                }
            }
        }

        private int SiteId
        {
            get
            {
                if (this.Page is TemplatePage)
                {
                    return ((TemplatePage)this.Page).SiteId;
                }
                else
                {
                    Acms.Bll.Site site = Acms.Bll.Site.GetFromHttpRequest(Page.Request);
                    if (site != null)
                    {
                        return site.Id;
                    }
                    else
                    {
                        return 0;
                    }
                }
            }
        }

        void btnForgottenPassword_Click(object sender, EventArgs e)
        {
            currentMode = Mode.ForgottenPassword;
        }

        private TextBox InitTextBox(string id)
        {
            TextBox tmp = new TextBox();
            InitControl(tmp, id);
            return tmp;
        }

        private void InitControl(Control ctrl, string id)
        {
            ctrl.ID = id;
            this.Controls.Add(ctrl);
        }

        void btnLogon_Click(object sender, EventArgs e)
        {
            if (Page.IsValid)
            {
                int siteId = 0;
                if (Page is TemplatePage)
                {
                    siteId = ((TemplatePage)Page).SiteId;
                }
                else
                {
                    Acms.Bll.Site site = Acms.Bll.Site.GetFromHttpRequest(Page.Request);
                    if (site != null)
                    {
                        siteId = site.Id;
                    }
                }
                if (siteId == 0)
                {
                    throw new Acms.Exceptions.SiteNotFoundException();
                }

                Acms.Bll.UserSecurity user = Acms.Bll.UserSecurity.GetByUserName(username.Text, siteId);
                if (user != null)
                {
                    if (user.AuthenticatePassword(password.Text))
                    {
                        Guid key = user.GetLoginKey(cbRemember.Checked);
                        System.Web.Security.FormsAuthentication.SetAuthCookie(key.ToString(), cbRemember.Checked);
                        if (string.IsNullOrEmpty(returnUrl))
                        {
                            Page.Response.Redirect(Page.ResolveUrl("~/"));
                        }
                        else
                        {
                            Page.Response.Redirect(Page.ResolveUrl(returnUrl));
                        }
                    }
                    else
                    {
                        //invalid password
                        invalidPassword = true;
                    }
                }
                else
                {
                    //invalid username
                    invalidUsername = true;
                }
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
        }

        public override void RenderControl(HtmlTextWriter writer)
        {
            //wrapper div
            if(CurrentMode == Mode.Login)
            {
                writer.AddAttribute("OnKeyPress", string.Format("javascript:return WebForm_FireDefaultButton(event, '{0}')", btnLogon.ClientID));
            }
            else if(CurrentMode == Mode.ForgottenPassword)
            {
                writer.AddAttribute("OnKeyPress", string.Format("javascript:return WebForm_FireDefaultButton(event, '{0}')", btnSendForgottenPassword.ClientID));
            }
            writer.AddAttribute(HtmlTextWriterAttribute.Class, "login");
            writer.RenderBeginTag(HtmlTextWriterTag.Div);

            if (Page.Request.IsAuthenticated)
            {
                writer.Write("You are logged in as '{0}'.", Page.User.Identity.Name); 
            }
            else
            {

                if (CurrentMode == Mode.Login)
                {

                    if (invalidUsername || invalidPassword)
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.Class, ErrorMessageClass);
                        writer.RenderBeginTag(HtmlTextWriterTag.Div);

                        writer.Write(InvalidUserNameOrPasswordMessage);

                        writer.RenderEndTag();
                    }

                    //wrapper ul
                    writer.RenderBeginTag(HtmlTextWriterTag.Ul);

                    //user name
                    writer.RenderBeginTag(HtmlTextWriterTag.Li);
                    RenderLoginUsername(writer);
                    writer.RenderEndTag();

                    //password
                    writer.RenderBeginTag(HtmlTextWriterTag.Li);
                    RenderLoginPassword(writer);
                    writer.RenderEndTag();

                    //remember me
                    writer.RenderBeginTag(HtmlTextWriterTag.Li);
                    RenderLoginRememberMe(writer);
                    writer.RenderEndTag();

                    //button
                    writer.RenderBeginTag(HtmlTextWriterTag.Li);
                    RenderLoginButtons(writer);
                    writer.RenderEndTag();

                    writer.RenderEndTag();//ul
                }
                else
                {
                    if (invalidEmail)
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.Class, ErrorMessageClass);
                        writer.RenderBeginTag(HtmlTextWriterTag.Div);

                        writer.Write(EmailNotFoundMessage);

                        writer.RenderEndTag();
                    }
                    else if (sentEmail)
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.Class, MessageClass);
                        writer.RenderBeginTag(HtmlTextWriterTag.Div);

                        writer.Write(SentForgottenPasswordMessage);

                        writer.RenderEndTag();
                    }
                    else
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.Class, MessageClass);
                        writer.RenderBeginTag(HtmlTextWriterTag.Div);

                        writer.Write(ForgottenPasswordInstructions);

                        writer.RenderEndTag();
                    }

                    //wrapper ul
                    writer.RenderBeginTag(HtmlTextWriterTag.Ul);
                    
                    writer.RenderBeginTag(HtmlTextWriterTag.Li);
                    RenderForgottenEmail(writer);
                    writer.RenderEndTag();

                    writer.RenderBeginTag(HtmlTextWriterTag.Li);
                    RenderForgottenButtons(writer);
                    writer.RenderEndTag();

                    writer.RenderEndTag();//ul
                }

            }
            writer.RenderEndTag();//div
        }

        private void RenderLoginUsername(HtmlTextWriter writer)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.For, username.ClientID);
            writer.RenderBeginTag(HtmlTextWriterTag.Label);
            writer.Write("Username:");
            writer.RenderEndTag();
            username.RenderControl(writer);
            valUsernameReq.RenderControl(writer);
        }

        private void RenderLoginPassword(HtmlTextWriter writer)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.For, password.ClientID);
            writer.RenderBeginTag(HtmlTextWriterTag.Label);
            writer.Write("Password:");
            writer.RenderEndTag();
            password.RenderControl(writer);
            valPasswordReq.RenderControl(writer);
        }

        private void RenderLoginRememberMe(HtmlTextWriter writer)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.For, password.ClientID);
            writer.RenderBeginTag(HtmlTextWriterTag.Label);
            writer.Write("Remember me next time?");
            writer.RenderEndTag();
            cbRemember.RenderControl(writer);
        }

        private void RenderLoginButtons(HtmlTextWriter writer)
        {
            btnLogon.RenderControl(writer);
            btnForgottenPassword.RenderControl(writer);
        }

        private void RenderForgottenEmail(HtmlTextWriter writer)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.For, txtEmail.ClientID);
            writer.RenderBeginTag(HtmlTextWriterTag.Label);
            writer.Write("Email Address:");
            writer.RenderEndTag();

            txtEmail.RenderControl(writer);
            valEmailReq.RenderControl(writer);
        }

        private void RenderForgottenButtons(HtmlTextWriter writer)
        {
            btnSendForgottenPassword.RenderControl(writer);
            btnCancelForgottenPassword.RenderControl(writer);
        }
    }
}
